package com.moxie.liveness;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.Log;

import com.linkface.liveness.LFLivenessSDK;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;

public class MXLivenessSDK {
    private static final String TAG = MXLivenessSDK.class.getSimpleName();
    private Context mContext;
    public static final int MX_LIVENESS_INIT_SUCCESS = 0;
    public static final int MX_LIVENESS_INIT_FAIL_LICENSE_OUT_OF_DATE = -15;
    public static final int MX_LIVENESS_INIT_FAIL_BIND_APPLICATION_ID = -14;
    public static final int MX_LIVENESS_INIT_FAIL_LICENCE_ILLEGALITY = -13;
    public static final int MX_LIVENESS_INIT_FAIL_MODEL_OUT_OF_DATA = -9;
    @SuppressLint({"StaticFieldLeak"})
    private static MXLivenessSDK mInstance;
    private static LFLivenessSDK mLFLivenessSdk;

    private MXLivenessSDK(Context context) {
        this.mContext = context;
        mLFLivenessSdk = LFLivenessSDK.getInstance(context);
        synchronized(this.getClass()) {
            this.copyModelIfNeed("track_2.1.1.model");
            this.copyModelIfNeed("liveness_2.0_half.model");
            this.copyModelIfNeed("detect_5.1.1.model");
        }
    }

    public static MXLivenessSDK getInstance(Context context) {
        if (mInstance == null) {
            Class var1 = MXLivenessSDK.class;
            synchronized(MXLivenessSDK.class) {
                if (mInstance == null) {
                    mInstance = new MXLivenessSDK(context);
                }
            }
        }

        return mInstance;
    }


    public int createHandle() {
        return mLFLivenessSdk.createHandle();
    }

    private void copyModelIfNeed(String modelName) {
        String path = this.getModelPath(modelName);
        if (path != null) {
            File modelFile = new File(path);
            if (modelFile.exists()) {
                modelFile.delete();
            }

            try {
                InputStream in = this.mContext.getApplicationContext().getAssets().open(modelName);
                OutputStream out = new FileOutputStream(modelFile);
                byte[] buffer = new byte[4096];

                int n;
                while((n = in.read(buffer)) > 0) {
                    out.write(buffer, 0, n);
                }

                in.close();
                out.close();
            } catch (IOException var8) {
                modelFile.delete();
                Log.e(TAG, var8.getLocalizedMessage(), var8);
            }
        }

    }

    @SuppressLint({"NewApi"})
    protected String getModelPath(String modelName) {
        String path = null;
        if (this.mContext == null) {
            return null;
        } else {
            File dataDir = this.mContext.getApplicationContext().getExternalFilesDir((String)null);
            boolean isExternal = true;
            if (dataDir != null) {
                path = dataDir.getAbsolutePath() + File.separator + modelName;

                try {
                    File tempFile = File.createTempFile("temp_", (String)null, dataDir);
                    tempFile.delete();
                } catch (IOException var6) {
                    var6.printStackTrace();
                    Log.e(TAG, "error msg: " + var6.getMessage());
                    isExternal = false;
                }
            }

            if (!isExternal) {
                dataDir = this.mContext.getApplicationContext().getFilesDir();
                path = dataDir.getAbsolutePath() + File.separator + modelName;
            }

            return path;
        }
    }

    public synchronized void destroy() {
        mLFLivenessSdk.destroy();
    }

    public synchronized boolean start(int config) {
        return mLFLivenessSdk.start(config);
    }

    public void setWrapperStaticInfo() {
        mLFLivenessSdk.setWrapperStaticInfo();

    }

    public static boolean isRootSystem() {
        return mLFLivenessSdk.isRootSystem();
    }

    public synchronized MXLivenessSDK.MXStatus detect(byte[] image, int width, int height, int rotateAngle, MXLivenessSDK.MXLivenessMotion motion) {
        LFLivenessSDK.LFLivenessMotion LFMotion = LFLivenessSDK.LFLivenessMotion.valueOf(motion.name());
        LFLivenessSDK.LFStatus lfResult = mLFLivenessSdk.detect(image,width,height,rotateAngle,LFMotion);
        MXLivenessSDK.MXStatus resultstatus =new MXLivenessSDK.MXStatus();
        resultstatus.setDetectStatus(lfResult.getDetectStatus());
        resultstatus.setPassed(lfResult.isPassed());
        return resultstatus;
    }

    public MXLivenessSDK.MXRect getFaceRect() throws Exception {
        LFLivenessSDK.LFRect lfRect = mLFLivenessSdk.getFaceRect();
        MXLivenessSDK.MXRect rect = new MXLivenessSDK.MXRect();
        rect.top = lfRect.top;
        rect.right = lfRect.right;
        rect.bottom = lfRect.bottom;
        rect.left = lfRect.left;
        return rect;
    }

    public synchronized void end() {
        mLFLivenessSdk.end();

    }

    public synchronized byte[] getLivenessResult() throws Exception {
        return mLFLivenessSdk.getLivenessResult();
    }

    public synchronized MXLivenessSDK.MXLivenessImageResult[] getImageResult() throws Exception {
        LFLivenessSDK.LFLivenessImageResult[] lfImageResults=mLFLivenessSdk.getImageResult();
        MXLivenessSDK.MXLivenessImageResult[] resultImageResult= new MXLivenessSDK.MXLivenessImageResult[lfImageResults.length];
        for (int i=0;i<lfImageResults.length;i++){
            MXLivenessImageResult mxResult=new MXLivenessImageResult();
            mxResult.image=lfImageResults[i].image;
            mxResult.motion=lfImageResults[i].motion;
            mxResult.length=lfImageResults[i].length;
            resultImageResult[i]=mxResult;
        }
        return resultImageResult;
    }

    public synchronized byte[] getVideoResult() throws Exception {
        return mLFLivenessSdk.getVideoResult();
    }

    public void initLicName(String licenseName) {
        mLFLivenessSdk.initLicName(licenseName);
    }

    public void initLicPath(String licPath, String licenseName) {
        mLFLivenessSdk.initLicPath(licPath,licenseName);
    }

    public String getLicPath() {
        return mLFLivenessSdk.getLicPath();
    }

    public int getRemainingDays() {
        return mLFLivenessSdk.getRemainingDays();
    }

    public String getLicenseTime() {
        return mLFLivenessSdk.getLicenseTime();
    }

    public boolean checkLicenseValid() {
        return mLFLivenessSdk.checkLicenseValid();
    }

    public synchronized void setStaticInfo(int key, String input) throws Exception {
        mLFLivenessSdk.setStaticInfo(key,input);
    }

    public synchronized void addSequentialInfo(int key, String input) throws Exception {
        mLFLivenessSdk.addSequentialInfo(key, input);
    }

    public static String getSDKVersion() {
        return LFLivenessSDK.getSDKVersion();
    }

    public class MXLivenessResult {
        public float left = 0.0F;
        public float top = 0.0F;
        public float right = 0.0F;
        public float bottom = 0.0F;
        public float score = 0.0F;
        public float[] points_array = new float[42];
        public int points_count = 0;
        public int yaw = 0;
        public int pitch = 0;
        public int roll = 0;
        public int eye_dist = 0;
        public int ID = 0;
        public boolean passed = false;
        public int message = 0;
        public int trackStatus = 0;

        public MXLivenessResult() {
        }
    }

    public static class MXLivenessImageResult implements Serializable {
        public byte[] image = null;
        public int length = 0;
        public int motion = 0;

        public MXLivenessImageResult() {
        }
    }

    public class MXRect {
        public float left = 0.0F;
        public float top = 0.0F;
        public float right = 0.0F;
        public float bottom = 0.0F;

        public MXRect() {
        }
    }

    public static enum MXTrackStatus {
        PASSED(0),
        FACE_OUTOF_BOUND(-10),
        FACE_TOO_FAR(-11),
        FACE_TOO_CLOSE(-12);

        private int mValue;

        private MXTrackStatus(int value) {
            this.mValue = value;
        }

        public int getValue() {
            return this.mValue;
        }
    }

    public static enum MXDetectStatus {
        PASSED(0),
        DETECTING(-1),
        INTERNAL_ERROR(-2),
        TRACKING_MISSED(-8);

        private int mValue;

        private MXDetectStatus(int value) {
            this.mValue = value;
        }

        public int getValue() {
            return this.mValue;
        }
    }

    public static class MXStatus {
        private int detectStatus;
        private boolean passed;

        public MXStatus() {
        }

        public boolean isPassed() {
            return this.passed;
        }

        public void setPassed(boolean passed) {
            this.passed = passed;
        }

        public int getDetectStatus() {
            return this.detectStatus;
        }

        public void setDetectStatus(int detectStatus) {
            this.detectStatus = detectStatus;
        }
    }

    public static enum MXDetectInfo {
        DETECTINFO((LFLivenessSDK.LFLivenessResult)null);

        private LFLivenessSDK.LFLivenessResult mValue;

        private MXDetectInfo(LFLivenessSDK.LFLivenessResult value) {
            this.mValue = value;
        }

        public LFLivenessSDK.LFLivenessResult getValue() {
            return this.mValue;
        }
    }

    public static enum MXWrapperSequentialInfo {
        ACCLERATION(0),
        ROTATION_RATE(1),
        GRAVITY(2),
        MAGNETIC_FIELD(3);

        private int mValue;

        private MXWrapperSequentialInfo(int value) {
            this.mValue = value;
        }

        public int getValue() {
            return this.mValue;
        }
    }

    public static enum MXLivenessOutputType {
        WRAPPER_OUTPUT_TYPE_SINGLE_IMAGE("singleImg", 0),
        WRAPPER_OUTPUT_TYPE_MULTI_IMAGE("multiImg", 1),
        WRAPPER_OUTPUT_TYPE_LOW_QUALITY_VIDEO("video", 2),
        WRAPPER_OUTPUT_TYPE_HIGH_QUALITY_VIDEO("fullVideo", 3);

        private final String mString;
        private int mValue = -1;

        private MXLivenessOutputType(String string, int value) {
            this.mValue = value;
            this.mString = string;
        }

        public int getValue() {
            return this.mValue;
        }

        public static MXLivenessSDK.MXLivenessOutputType getOutputTypeByValue(String value) {
            MXLivenessSDK.MXLivenessOutputType[] var1 = values();
            int var2 = var1.length;

            for(int var3 = 0; var3 < var2; ++var3) {
                MXLivenessSDK.MXLivenessOutputType outputType = var1[var3];
                if (outputType.mString.equalsIgnoreCase(value)) {
                    return outputType;
                }
            }

            return WRAPPER_OUTPUT_TYPE_MULTI_IMAGE;
        }
    }

    public static enum MXLivenessComplexity {
        WRAPPER_COMPLEXITY_EASY("easy", 0),
        WRAPPER_COMPLEXITY_NORMAL("normal", 256),
        WRAPPER_COMPLEXITY_HARD("hard", 512),
        WRAPPER_COMPLEXITY_HELL("hell", 768);

        private int mValue = -1;
        private String mString = null;

        private MXLivenessComplexity(String string, int value) {
            this.mValue = value;
            this.mString = string;
        }

        public int getValue() {
            return this.mValue;
        }

        public static MXLivenessSDK.MXLivenessComplexity getComplexityByValue(String value) {
            MXLivenessSDK.MXLivenessComplexity[] var1 = values();
            int var2 = var1.length;

            for(int var3 = 0; var3 < var2; ++var3) {
                MXLivenessSDK.MXLivenessComplexity complexity = var1[var3];
                if (complexity.mString.equalsIgnoreCase(value)) {
                    return complexity;
                }
            }

            return WRAPPER_COMPLEXITY_NORMAL;
        }
    }

    public static enum MXWrapperStaticInfo {
        DEVICE(0),
        OS(1),
        SDK_VERSION(2),
        SYS_VERSION(3),
        ROOT(4),
        IDFA(5),
        CONTROL_SEQ(6),
        CUSTOMER(7);

        private int mValue;

        private MXWrapperStaticInfo(int value) {
            this.mValue = value;
        }

        public int getValue() {
            return this.mValue;
        }
    }

    public static enum MXLivenessMotion {
        NONE(-1),
        BLINK(0),
        MOUTH(1),
        YAW(2),
        NOD(3);

        private int mValue;

        private MXLivenessMotion(int value) {
            this.mValue = value;
        }

        public int getValue() {
            return this.mValue;
        }
    }
}
